package com.izhar.answeringmachine.Controller;

// @TODO 代码重构，用户代码运行结果一致包装成submitResult对象，insert到数据库.目前只写完了submitResult的mapper接口

import com.alibaba.fastjson.JSONObject;
import com.izhar.answeringmachine.Entity.Sample;
import com.izhar.answeringmachine.Entity.SubmitCode;
import com.izhar.answeringmachine.Entity.SubmitResult;
import com.izhar.answeringmachine.mapper.SubmitResultMapper;
import com.izhar.answeringmachine.service.*;
import com.izhar.answeringmachine.utils.ResultData;
import com.izhar.answeringmachine.utils.Utils;
import com.izhar.answeringmachine.utils.parametersToList;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 主控制器
 */
@Slf4j
@RestController
@RequestMapping("/CodeMachine")
public class MachineController {

    //用户代码写入临时文件
    @Autowired
    protected IWriteToFile writeToFile;

    //编译代码
    @Autowired
    protected ICompile compile;

    //运行代码
    @Autowired
    protected IRun run;

    @Autowired
    protected ICheckCodeService checkCodeService;

    @Autowired
    protected ISaveCodeResult saveCodeResult;


    @Autowired
    protected ISaveFail saveFail;

    public static final String RUN_SUCCESS = "200";


    /**
     * 已废弃
     * @param userId  用户id
     * @param questionId 题目id
     * @param code 用户代码
     * @param parameter 参数
     * @return 运行结果
     */
    @PostMapping("/runCode")
    @Deprecated
    public ResultData runCode(String userId,
                              String questionId,
                              String code,
                              @RequestParam(value = "parameter",required = false) List<String> parameter){


        if (userId==null || questionId==null || code==null) {
            return new ResultData("50025","run error","userId or QuestionId or code is empty");
        }
        //编写临时Java文件
        writeToFile.write(userId,questionId,code,null);
        //编译
        compile.compile(userId, questionId,null);
        //运行
        String result = this.run.run(userId, questionId,parameter,null);



        if (result!=null && !"".equals(result.trim())) {
            return new ResultData("200","run success", URLEncoder.encode(result,StandardCharsets.UTF_8));
        } else {
            return new ResultData("50010","Code run result is empty",null);
        }
    }




    /**
     * 通过id，拿到数据库中的用户代码，并且运行，
     * 50020 运行异常（超时，超内存）,50022其他异常，50023错误答案,200正确
      * @param id   用户提交代码的数据库行id
     * @return  运行结果
     */
    @RequestMapping("/check")
    public JSONObject checkCode(@RequestParam(value = "id") String id){

        //从数据库拿到要运行的用户代码
        ResultData resultData = checkCodeService.selectSubmitCode(id);
        SubmitCode submitCode = (SubmitCode) resultData.getData();

        String userId = submitCode.getUserId();
        String questionId = submitCode.getQuestionId();
        String code = submitCode.getCode();

        //配置代码运行结果类
        SubmitResult submitResult = new SubmitResult();
        submitResult.setId(Utils.generateId());
        submitResult.setQuestionId(questionId);
        submitResult.setUserId(userId);
        submitResult.setSubmitCodeId(submitCode.getId());
        submitResult.setCreateTime(new Date());


        //编写临时文件
        writeToFile.write(userId,questionId,code,submitResult);

        //编译文件
        compile.compile(userId, questionId,submitResult);

        //编译异常直接return
        if (!RUN_SUCCESS.equals(submitResult.getResultCode())){
            saveCodeResult.save(submitResult);
            return (JSONObject) JSONObject.toJSON(new ResultData(submitResult.getResultCode(),submitResult.getErrorDetail(),null));
        }

        //获取样例列表
        List<Sample> samples = checkCodeService.selectParameters(submitCode.getQuestionId());


        //通过多个样例运行代码
        for (Sample sample : samples) {
            //单个样例的代码参数，比如a+b程序的，a,b
            List<String> parameterList = parametersToList.getParameterList(sample);
            //用当前样例运行项目
            String result = this.run.run(userId, questionId,parameterList,submitResult);
            //发生超时或超内存，其他异常，代码返回result为空，
            if (result==null){
                saveCodeResult.save(submitResult);
                return (JSONObject) JSONObject.toJSON(new ResultData("50015",submitResult.getErrorDetail(),null));
            }

            //用户代码的输出和样例输出不一致 返回map 错误样例ID：错误结果
            if (!result.equals(sample.getOutSample())){

                submitResult.setResultCode("3");
                submitResult.setErrSampleId(sample.getId());
                submitResult.setErrResult(result);
                submitResult.setErrorDetail("error answer");

                //代码运行结果放到数据库
                saveCodeResult.save(submitResult);
                return (JSONObject) JSONObject.toJSON(new ResultData("50025","Wrong answer",null));
            }
        }


        submitResult.setResultCode("200");
        saveCodeResult.save(submitResult);
        return (JSONObject) JSONObject.toJSON(new ResultData("200","Right answer",null));
    }







    @PostMapping("/test")
    public void test(String username,String password,@RequestParam(value = "aihao",required = false) List<String> aihao){
        System.out.println(aihao);
    }
}